package ch.fusun.baron.weather;

import java.util.ArrayList;
import java.util.List;

/**
 * The automaton
 */
public class Automaton {

	private World world;
	private List<AutomatonUpdater> updaters;

	/**
	 * @param world
	 *            The world
	 */
	public void setWorld(World world) {
		this.world = world;
		updaters = new ArrayList<AutomatonUpdater>();
	}

	/**
	 * adds an automaton updater
	 * 
	 * @param automatonUpdater
	 */
	public void put(AutomatonUpdater automatonUpdater) {
		updaters.add(automatonUpdater);
	}

	/**
	 * Performs the next step
	 */
	public void step() {
		for (AutomatonUpdater updater : updaters) {
			World buffer = new World(this.world);
			Cube[][][] cubes = this.world.getCubes();
			for (int i = 0; i < cubes.length; i++) {
				for (int j = 0; j < cubes[i].length; j++) {
					for (int k = 0; k < cubes[i][j].length; k++) {
						Cube[][][] surrounding = createSourroundingCubes(world,
								i, j, k);

						updater.update(surrounding, buffer.getCubes()[i][j][k]);
					}

				}
			}
			this.world = new World(buffer);// write it back
		}
	}

	private static Cube[][][] createSourroundingCubes(World w, int i, int j,
			int k) {
		Cube[][][] cubes = w.getCubes();
		int xLength = cubes.length;
		int yLength = cubes[0].length;
		int zLenght = cubes[0][0].length;
		Cube[][][] result = new Cube[3][3][3];

		for (int x = -1; x <= 1; x++) {
			for (int y = -1; y <= 1; y++) {
				for (int z = -1; z <= 1; z++) {
					result[x + 1][y + 1][z + 1] = cubes[(i + x + xLength)
							% xLength][(j + y + yLength) % yLength][(k + z + zLenght)
							% zLenght];
				}
			}
		}
		return result;
	}

	/**
	 * @return The world
	 */
	public World getWorld() {
		return this.world;
	}
}
